/*!
    \copyright  Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
                All rights reserved.
                Confidential and Proprietary - Qualcomm Technologies, Inc.
    \version    
    \file       dfu_transport_relay_priv.h
    \ingroup    dfu
    \brief      Control and Manage Data Transfer to Peer through Tranport Layer.
*/

#include "dfu_transport_relay.h"

/*! \brief Message IDs from Upgrade Peer to main application task */
typedef enum
{
    DFU_TRANSPORT_RELAY_STATE_IDLE = 0,          /*! DFU Transport Relay is not initialized or upgrade is not in data transfer */
    DFU_TRANSPORT_RELAY_STATE_DATA_TRANSFER = 1, /*! DFU Transport Relay is collating the required offsets and sending request */
} dfu_transport_relay_state_t;

/*! \brief Info stored about every stream of data that dfu_transport_relay is servicing */
typedef struct
{
    bool        is_active;
    uint32      requested_size;
    uint32      pending_size;
    uint32      offset;
} dfu_relay_stream_info_t;


/*! \brief Information stored by the dfu_transport_relay task */
typedef struct
{
    TaskData        MyTask;

    dfu_transport_relay_state_t     state;

    bool primary_requested_data;

    bool secondary_requested_data;
} dfu_transport_relay_task_data_t;

typedef struct {
    uint16 length;
    uint16 lastPacket;
    const uint8 *data;
    /* A pre-built confirmation message that the handler can send to transport task once
     * the message is handled. */
    void* dataCfm;
    Task transportTask;
    /* No of bytes left to send to peer */
    uint16 pending_to_process;
} UPGRADE_TRANSPORT_RELAY_PEER_DATA_WITH_ACK_T;

typedef struct
{
    /*! Queue to store incoming DATA messages from host if they arrive while we are processing previous message. */
    UPGRADE_TRANSPORT_RELAY_PEER_DATA_WITH_ACK_T** data_queue;

    /*! Current size of queue (elements stored in it). */
    uint16 queue_size;

    /*! Max capacity of the queue. */
    uint16 queue_max_size;

    /* Points to the first available element at the head of queue. */
    uint16 queue_head;

    /* Points to next available position at the tail of queue */
    uint16 queue_tail;

    /* Data stream info for Self */
    dfu_relay_stream_info_t dfu_relay_stream_self;

    /* Data stream info for Peer */
    dfu_relay_stream_info_t dfu_relay_stream_peer;

    /* Data stream info for requested partition*/
    dfu_relay_stream_info_t dfu_relay_stream_incoming;
} dfu_transport_relay_context_t;

/*! \brief Get state of DfuTransportRelay

    \return State of DfuTransportRelay
*/
dfu_transport_relay_state_t dfuTransportRelayGetState(void);

/*! \brief Set state of DfuTransportRelay module

    \return none
*/
void dfuTransportRelaySetState(dfu_transport_relay_state_t state);

/*! \brief Handle the SM when in Data Transfer State

    Handle messages received when SM in in Data Transfer State

    \return True, if the message is handled, else FALSE.
*/
bool dfuTransportRelayHandleDataTransfer(MessageId id, Message message);

/*! \brief Handle the SM when in Idle State

    Handle messages received when SM in in Idle State

    \return True, if the message is handled, else FALSE.
*/
bool dfuTransportRelayHandleIdle(MessageId id, Message message);

/*! \brief Handle messages not handled in any of the state handlers

    \return None
*/
void dfuTransportRelayDefaultHandler(MessageId id, Message message);

/*! \brief Handle messages sent to DFU_TRASPORT_RELAY module 

    Common function to handle messages send to dfu_transport_relay, assign 
    message based on the current state

    \return none
*/
void dfuTransportRelayMessageHandler(Task task, MessageId id, Message message);

/*! \brief Send Data Bytes request to host

    Collate the final offset and size and send the data request to host.

    \return none
*/
void dfuTransportRelaySendDataReq(void);

/*! \brief Compare the offsets requested by device and peer and return lower offset

    \return Final offset to request from host
*/
uint32 dfuTransportRelayOffsetCalculator(void);

/*! \brief Compare the offsets requested by device and peer and return size corresponding to lower offset.

    \return Final data_bytes to request from host
*/
uint32 dfuTransportRelayReqSizeCalculator(void);

/*! \brief When UPGRADE_HOST_DATA packets are received, add to queue to send to peer

    \return None
*/
void dfuTransportRelayEnqueueMsg(UPGRADE_TRANSPORT_RELAY_PEER_DATA_WITH_ACK_T* msg);

/*! \brief Remove the element from the head of the queue
    \return None
*/
void dfuTransportRelayDequeueData(void);

/*! \brief Return the element from the head of the queue
    \return Last message
*/
UPGRADE_TRANSPORT_RELAY_PEER_DATA_WITH_ACK_T* dfuTransportRelayGetQueueHead(void);

/*! \brief Process the data received from host and stream data bytes to self device
    \return None
*/
void dfuTransportRelayDataSendDataToSelf(UPGRADE_HOST_DATA_WITH_ACK_T* msg);

/*! \brief Process the data received from host and stream data bytes to peer device
    \return None
*/
void dfuTransportRelayDataSendDataToPeer(UPGRADE_HOST_DATA_WITH_ACK_T* msg);

/*! \brief Update the pending_size and is_active fields of incoming stream
    \return None
*/
void dfuTransportRelayUpdateIncomingStream(uint16 length);

/*! \brief Update the pending_size and is_active fields of self stream
    \return None
*/
void dfuTransportRelayUpdateSelfStream(uint16 length);

/*! \brief Update the pending_size and is_active fields of peer stream
    \return None
*/
void dfuTransportRelayUpdatePeerStream(uint16 length);

/*! \brief Write data to peer L2CAP Sink

    Request the available slack in L2CAP connection with peer, retrieve data 
    from queue, and write to the sink.

    \return None
*/
void dfuTransportRelayDataWriteToPeer(void);
